from PyQt6 import QtWidgets
from PyQt6 import QtGui, QtCore
from PyQt6 import uic
from PyQt6.QtWidgets import QMainWindow
from PyQt6.QtCore import pyqtProperty, pyqtSignal

import sys

import client_core
from client_ui import LoginDialog
from client_core import QAsyncSsdevClient, QAsyncSsdevRpcResolver, SsdevRpcNode

import qasync
import asyncio
from functools import partial
from qasync import asyncSlot, asyncClose, QApplication


class Ui(QMainWindow):

    client_ok = pyqtSignal(QAsyncSsdevClient)
    enter_service = pyqtSignal(SsdevRpcNode)

    def __init__(self):
        super(Ui, self).__init__()
        self.client: QAsyncSsdevClient = None
        self.resolver: QAsyncSsdevRpcResolver = None

        uic.loadUi('MainWindow.ui', self)
        self.error_dialog = QtWidgets.QErrorMessage()

        self.service_model = QtGui.QStandardItemModel()
        self.treeService.setModel(self.service_model)

        self.bConnect.clicked.connect(self.on_connect_button_clicked)
        self.client_ok.connect(self.on_client_ok)
        self.treeService.activated.connect(self.on_tree_service_activated)
        self.enter_service.connect(self.on_enter_service)

        #self.treeService.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)

    def show_error(self, ctx, msg):
        QtWidgets.QMessageBox.critical(self, "Error", msg)

    def on_connect_button_clicked(self):
        url = self.eUrl.text()
        dialog = LoginDialog(self, url)
        dialog.exec()
        dialog.close()

    @asyncSlot(QAsyncSsdevClient)
    async def on_client_ok(self, client: QAsyncSsdevClient):
        print('on_client_ok')
        client.setParent(self)
        resolver = QAsyncSsdevRpcResolver(client, parent=self)

        self.client = client
        self.resolver = resolver

        node = await resolver.walk_tree(None)

        self.service_model.clear()
        self.service_model.appendRow(node.standard_item)

        index = self.service_model.indexFromItem(node.standard_item)
        self.treeService.expand(index)

    def on_tree_service_activated(self, index: QtCore.QModelIndex, *args):
        if index.isValid():
            node: SsdevRpcNode = index.data(QtCore.Qt.ItemDataRole.UserRole)
            if node is not None and node.node_type == 3:
                self.enter_service.emit(node)

    @asyncSlot(SsdevRpcNode)
    async def on_enter_service(self, node: SsdevRpcNode):

        print(node.path)
        print(node.name)
        print(node.parameters)


async def qt_async_main():
    def close_future(future: 'asyncio.Future', loop):
        loop.call_later(10, future.cancel)
        future.cancel()

    loop = asyncio.get_event_loop()
    future = asyncio.Future()

    app = QApplication.instance()
    # app = QApplication(sys.argv)
    if hasattr(app, "aboutToQuit"):
        getattr(app, "aboutToQuit").connect(
            partial(close_future, future, loop)
        )
    main_window = Ui()
    main_window.show()

    await future
    return True

if __name__ == "__main__":
    try:
        qasync.run(qt_async_main())
    except asyncio.exceptions.CancelledError:
        sys.exit(0)
